<template>
<div>
  <!--三级分类卡片-->
  <el-card>
    <CategorySelector @idChange="idChange" ref="cs"></CategorySelector>
  </el-card>

  <!--属性列表渲染的卡片-->
  <el-card v-show="showList">
    <!--添加按钮-->
    <!--category3Id为""的时候要禁用 disabled值为true-->
    <el-button type="primary" icon="el-icon-circle-plus-outline"
               :disabled="!category3Id" @click="showAdd">添加属性</el-button>
    <!--属性列表  data:[{attrName:"xxx",...},{attrName:"yyyy"}]-->
    <el-table style="margin-top: 20px" border :data="attrs" v-loading="loading">
      <el-table-column align="center" label="序号" type="index" width="80"></el-table-column>
      <el-table-column align="center" label="属性名称" prop="attrName"></el-table-column>
      <el-table-column align="center" label="属性值列表" width="680">
        <!--row:代表的是当前行-->
        <template slot-scope="{row}">
            <el-tag type="info" v-for="valObj in row.attrValueList" style="margin-right: 5px">
              {{valObj.valueName}}
            </el-tag>
        </template>
      </el-table-column>
      <el-table-column align="center" label="操作">
        <template slot-scope="{row}">
          <HintButton title="修改属性" type="primary" icon="el-icon-edit"
                      size="mini" @click="showEdit(row)"></HintButton>

          <el-popconfirm :title="`确定删除${row.attrName}吗？`"  @onConfirm="delAttr(row.id)">
            <HintButton title="删除属性" type="danger" icon="el-icon-delete" slot="reference"
                        size="mini" ></HintButton>
          </el-popconfirm>
        </template>
      </el-table-column>
    </el-table>
  </el-card>

  <!--新增&编辑对应的卡片-->
  <el-card v-show="!showList">
    <el-form inline>
      <el-form-item label="属性名">
        <!--v-model使用在组件上实现的还是数据的双向绑定-->
        <el-input placeholder="请输入属性名" v-model="attr.attrName"></el-input>
      </el-form-item>
    </el-form>

    <!--attr.attrName为""的时候 下面的el-button要禁用 disabled应该为true-->
    <el-button type="primary"  :disabled="!attr.attrName"
               icon="el-icon-circle-plus-outline" @click="addAttrValue">添加属性值</el-button>
    <el-button @click="showList = true;flagForDog3=false">取消</el-button>


    <!--attrValueList:[{valueName:'属性值',isEdit:true},{}]-->
    <el-table border  style="margin: 20px 0" :data="attr.attrValueList">
      <el-table-column label="序号" type="index" width="80" align="center"></el-table-column>
      <el-table-column label="属性值名称">
        <template slot-scope="{row,$index}">
          <span style="display: inline-block;width: 100%" v-if="!row.isEdit" @click="toEdit(row,$index)">{{row.valueName}}</span>
          <el-input :ref="`input${$index}`" v-else
                    v-model="row.valueName"  @keyup.enter.native="toSpan(row)"
                    @blur="toSpan(row)"></el-input>
        </template>
      </el-table-column>
      <el-table-column label="操作">
        <template slot-scope="{row,$index}">
          <el-popconfirm :title="`确定删除${row.valueName}吗？`"  @onConfirm="attr.attrValueList.splice($index,1)">
            <HintButton title="删除" slot="reference" type="danger" icon="el-icon-delete" size="mini"></HintButton>
          </el-popconfirm>
        </template>
      </el-table-column>
    </el-table>

    <!--保存按钮禁用的逻辑 : true: attr.attrName为"" 或 attr.attrValueList为空数组-->
    <el-button type="primary" :disabled="disableForSave" @click="save">保存</el-button>
    <el-button @click="showList = true;flagForDog3=false">取消</el-button>
  </el-card>
</div>
</template>

<script>
import cloneDeep from "lodash/cloneDeep"
export default {
  name: 'AttrList',
  data(){
    return {
      category1Id:"",
      category2Id:"",
      category3Id:"",
      attrs:[] ,//存放分类对应的属性列表
      showList:true,//属性列表界面是否隐藏
      attr:{  //代表当前编辑 / 添加的属性
        attrName:"",
        attrValueList:[] //[{valueName,isEdit}....]
      },
      flagForDog3:false, //flagForDog3:true 输入框的内容为空 输入框的内容重复
      loading:false //每次列表界面渲染时的loading动画的开关
    }
  },
  computed:{
    disableForSave(){
      //本来直接使用data中的flagForDog3就可以实现以下功能 但是data中的flagForDog3初始化的时候写死了为false
      //所以我们要安装data中的flagForDog3逻辑重新判断
      let flagForDog3 = false;  //为""不行 一定要为false
      let index = this.attr.attrValueList.length-1;
      if(index>=0){
        let valueName = this.attr.attrValueList[index].valueName;//代表最新那个输入框中的值
        // 输入框的内容为空 输入框的内容重复 时保存按钮也得处于禁用状态
        let dog1 = valueName.trim();
        let dog2 = this.attr.attrValueList.filter(attrValue => attrValue.valueName === valueName)
        if(dog1==="" || dog2.length>=2){ //一定要大于等于
          // 保存按钮也得处于禁用状态
          flagForDog3 = true;
        }
      }else{
        //table为空时  保存按钮必须为禁用状态
        flagForDog3 = true
      }

      console.log(index,flagForDog3,!this.attr.attrName || this.attr.attrValueList.length===0 || flagForDog3);
      return !this.attr.attrName || this.attr.attrValueList.length===0 || flagForDog3
    }
  },
  methods:{
    //当三级分类的id产生变化时 自动调用的函数
    idChange({id,level}){
      //当三级分类产生变化的时候 我们要发送请求去获取分类对应的属性数据
      switch (level){
        case 1:
          //当一级分类产生变化 当前组件中的category2Id category3Id arrs得重置
          this.category1Id = id;
          this.category2Id = "";
          this.category3Id = "";
          this.attrs = []
          break;
        case 2:
          //当二级分类产生变化 当前组件中的category3Id arrs得重置
          this.category2Id = id;
          this.category3Id = "";
          this.attrs = []
          break;
        case 3:
          this.category3Id = id;
          this.getAttr()
          break;
      }
    },
    //显示属性编辑界面
    showEdit(row){
      //row :{attrnName,attrValuelist:[{valueName,isEdit}]}
      //将列表界面隐藏 将编辑界面显示
      this.showList = false
      //row 代表的是当前行的数据
      //添加 和 修改 不一样的地方
      // this.attr = row;
      this.attr = cloneDeep(row)
    },
    //显示属性添加界面
    showAdd(){
      //将列表界面隐藏 添加界面显示
      this.showList = false
      //重置attr  不然数据会产生污染
      this.attr = {
        attrName:"",
        attrValueList:[]
      };
    },
    //为对应的属性去添加属性值
    addAttrValue(){
      //看一下当前添加时  上一次添加是不是出于失败状态
      if(this.flagForDog3) return

      //构建一个属性值对象
      const value = {
        valueName:"",
        isEdit:true //让属性值对应的界面处于编辑状态
      }
      //push方法是一个变异方法 [push方法每次调用时 界面都会重新更新
      this.attr.attrValueList.push(value)
      //让对应的input(最新的那一个)选中
      this.$nextTick(()=>{
        this.$refs[`input${this.attr.attrValueList.length-1}`].focus()
      })
    },
    //当从一个input身上失去焦点 或者 按了回车键之后 要切换到显示模式;(span)
    toSpan(row){

      //养两条狗咬住逻辑
      //1. 如果输入的值为空 则不让切换到显示模式
      let dog1 = row.valueName.trim();
      if(dog1 === ""){
        this.flagForDog3 = true; //代表当次添加失败
        this.$message({
          showClose: true,
          message: '属性值名称不能为空',
          type: 'warning'
        });
        return;
      }
      //2. 如果输入的值重复 则不让切换到显示模式
      //必须找到两条以上的数据和row.valueName同名  我们才能去return
      let dog2 = this.attr.attrValueList.filter(attrValue => attrValue.valueName === row.valueName)
      if(dog2.length >= 2){
        this.flagForDog3 = true; //代表当次添加失败
        this.$message({
          showClose: true,
          message: '属性值名称不能重复',
          type: 'warning'
        });
        return;
      }


      //row 当前操作行对应的数据 (input能不能显示靠row.isEdit)
      //让span显示 让input消失
      this.flagForDog3 = false;
      row.isEdit = false
    },
    //当点击一个span后 切到对应的编辑模式(input)
    toEdit(row,index){

      //看一下当前切到编辑模式时  上一次添加是不是处于失败状态
      if(this.flagForDog3) return

      //row : 当前行对应的数据  {valueName,isEdit}
      //index: 当前行对应的index
      // row.isEdit = true;
      //编辑 和 添加 的一个区别
      if(row.hasOwnProperty("isEdit")){
        row.isEdit = true;
      }else{
        this.$set(row,"isEdit",true)
      }

      this.$nextTick(()=>{
        this.$refs[`input${index}`].focus()
      })
    },
    //获取属性列表
    async getAttr(){
      this.loading = true;
      const {data} = await this.$API.attr.getAttrs(this.category1Id,this.category2Id,this.category3Id)
      this.loading = false;
      this.attrs = data
    },
    //发送新增&修改请求
    async save(){
      // console.log(this.attr)
      let attr = {
        ...this.attr,
        categoryId: this.category3Id,
        categoryLevel: 3
      }
      //发送请求
      await this.$API.attr.add_updateAttr(attr);
      //提醒
      this.$message.success("保存成功")
      //关闭新增&修改界面 显示列表界面
      this.showList = true;
      //属性列表得到刷新
      await this.getAttr()
    },
    //发送请求删除属性
    async delAttr(id){
      await this.$API.attr.delAttrById(id)
      //提醒
      this.$message.success("删除成功")
      //属性列表得到刷新
      await this.getAttr()
    }
  },
  async mounted(){
    //最后要删除的代码
   /* this.category1Id=1,
    this.category2Id=1,
    this.category3Id=1
    const {data} = await this.$API.attr.getAttrs(this.category1Id,this.category2Id,this.category3Id)
    this.attrs = data*/
  },
  watch:{
    showList(val){
      //val : showList最新改变的值
      this.$refs.cs.disabled = !val
    }
  }
}
</script>
